package IO;

/*
首先理解几个概念
1、字节文件：一个个字节组成，由数值在内存中的编码表示。
2、文本文件（本质上也是字节文件）：也是一个个字节组，由数值字符表示。
思考：120 的表示
字节文件:四个字节，120的补码
文本文件：120，三个字节，“1”，“2”，“0”
字节流：
FileInputStream：字节文件的读
FileOutputStream：字节文件的写
*/
/*
【文件输入流】
举例：
*/
//将D:\test.txt（不含汉字）内容在屏幕上打印
/*
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.BufferedReader;
public class 输入与输出 {
	public static void main(String [] args) throws Exception {
//		try (FileInputStream fis=new FileInputStream("d:\\test2");
//				FileOutputStream fos=new FileOutputStream("d:\\test2") ){
//		try (FileReader fr= new FileReader("d:\\test.txt")){
		try (BufferedReader fr =new BufferedReader(new FileReader("d:\\test.txt"))) {
			//有格式的文本文件写
			//PrintWriter pw=new PrintWriter("d:/t.txt")
			//pw.print(内容)或pw.println(内容)
			String c;
			while((c=fr.readLine())!=null) {
				System.out.println(""+c);
			}
//			fos.write(97);
		}
	}
}
*/
/*
//任意文件的复制
//只能是字节流来做，不能是字符流——因为字符流内部存在编码转换
FileInputStream fis1=new FileInputStream("d:/bk.jpg");
FileOutputStream fos=new FileOutputStream("w:/bk.jpg");//此时，文件已经创建但内容为空而已。
int ch;//byte[] ch=new byte[1024*1024];缓冲区技术，缩短时间
//int n
while((ch=fis1.read())!=-1)//while((n=fis1.read(ch))!=-1)//尽可能将ch读满
{
fos.write(ch);//fos.write(ch,0,n)；
}
fis1.close();
fos.close();
按java基本数据类型从字节文件中读和写
举例：现有字节文件存储50个整数，读出50个整数并求和与平均值
分析：如果调用FileInputStream的read()方法，每次仅能读一个字节，而我们需要4个字节组成的整数值，并不是一个字节的补码组成
的四个字节。所以我们需要对每4个字节进行处理，还原成整数值。所以这里使用新的两个类。
DataInputStream:包含了FileInputStream所有功能

DataInputStream(InputStream in)//构造器，只要是InputStream的子类都可以作为输入
readxxx()//xxx指java基本数据类型
public final int readInt() throws IOException//内部调用read()读取四次，再根据补码拼装成int返回
double readDouble()//内部调用read()读取八次，再根据补码拼装成double返回
readInt()：如何判断结束
如果读到文件结束，将抛出EOFException

DataInputStream dis=new DataInputStream(
new FileInputStream("data.dat")
);
int v;
try{
while(true){v=dis.readInt();//对v进行处理
}
}
catch(EOFException e){}
dis.close();
DataOutputStream

DataOutputStream dos=new DataOutputStream(
new FileOutputStream("d:/data.dat")
);
for(int i=1;i<=50;i++)dos.writeInt(i);
dos.flush();
dos.close();
字符流（文本流）
文本文件读：
FileReader，以字符为单位
文本文件写：
FileWriter

//文本文件以字符为单位读，d盘下有文本文件t
FileReader fr=new FileReader("d:/t.txt");
int ch1;
while((ch1=fr.read())!=-1){System.out.print(" "+(char)ch1);
}
fr.close()
//文本文件写，以字符为单位
FileWriter fw=new FileWrite("d:/t.txt");
String sttr="Hello java";
fw.write(str);
fw.flush();
fw.close();
以文本行为单位的读
BufferReader：包含了FileReader的所有功能

String readLine();//读文本行
//以文本行为单位读取文件内容
BufferReader br=new BufferReader(
new FileReader("d:/t.txt")
);
//每次读取一行
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
文本文件有格式写
PrintWriter

//有格式的文本文件写
//99乘法表
PrintWriter pw=new PrintWriter("d:/t.txt");
for(int i=1;i<=9;i++){for(int j=1;j<=i;j++){pw.print(i+"*"+j+"="+i*j);}pw.println();
}
pw.flush();
pw.close();
文本文件读基本数据类型
Scanner（首选，可以取代BufferReader）

//Scanner用法1：从键盘上读入整数值
Scanner sc=new Scanner(System.in);
int v1=sc.nextInt();
//Scanner用法2：从文件中读取基本数据类型
Scanner sc= new Scanner(new File("d:/t.txt"));
while(sc.hasNextInt())//判断sc对象中是否还有下一个整数值
{int v=sc.nextInt();
}
//从串中读取
Scanner sc=new Scanner("    32    12    45");
whiile(sc.hasNextInt())
{int v=nextInt();
}//Scanner处理文本行
*/
//import java.io.FileInputStream;
import java.io.File;
import java.util.Scanner;
//文本文件读：FileReader，以字符为单位.文本文件写：FileWriter
//BufferReader：包含了FileReader的所有功能. 文本文件有格式写:PrintWriter
//Scanner（首选，可以取代BufferReader）
public class 输入与输出 {
	public static void main(String []args) throws Exception{
		//Scanner用法1：从键盘上读入整数值
		Scanner sc0=new Scanner(System.in);
		int v1=sc0.nextInt();
		System.out.println(v1);
		
		//Scanner用法2：从文件中读取基本数据类型
		try (Scanner sc1=new Scanner(new File("d:\\test1.txt"))){
			while(sc1.hasNextLine()){//判断sc对象中是否还有下一个整数值
				String line=sc1.nextLine();
				System.out.println(line);
			}
		}
		//从串中读取
		Scanner sc2=new Scanner("    32    12    45");
		while(sc2.hasNextInt()) {
			int v=sc2.nextInt();
			System.out.println(v);//Scanner处理文本行
		}
		//如何告诉Scanner数据之间的分割方法
		try (Scanner sc1=new Scanner(new File("d:\\test1.txt"))){
			//由逗号，空格，换行组成的分隔符
			//sc1.useDelimiter("[\\s,\\n]+");//useDelimiter(Pattern)说明分割符是什么，形参是正则式
			//test.txt内容：
			//120 111
			//120,222
			//120
			while(sc1.hasNextInt()){//判断sc对象中是否还有下一个整数值
				int line=sc1.useDelimiter("[\\s,\\n]+").nextInt();
				System.out.println(line);
				//输出：
				//120
				//111
				//120
				//222
				//120
			}
		}
	}
}
/*
Scanner类next() 与 nextLine() 区别
next():
1、一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白，next() 方法会自动将其去掉。
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
4、next() 不能得到带有空格的字符串。

nextLine()：
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
2、可以获得空白。
*/
